package com.zhl.framework.core.client;

import com.alibaba.fastjson.JSON;
import com.zhl.framework.core.common.RpcInvocation;
import com.zhl.framework.core.common.RpcProtocol;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

import static com.zhl.framework.core.common.cache.CommonClientCache.RESP_MAP;

/**
 * @Author: ZhangLu In DLUT
 * @since: 1.0.0
 * @Description: 编写客户端的入站处理器
 */
public class ClientHandler extends ChannelInboundHandlerAdapter {
    /**
     * 此方法调用在服务端发送数据给客户端(也就是 RPC 调用之后，方法的返回结果)，入站的时候回调用 channelRead 方法，ClientHandler 是一个入站处理器
     * @param ctx 通道上下文对象
     * @param msg 通道中的数据对象
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        RpcProtocol rpcProtocol = (RpcProtocol) msg;
        // 需要反序列化得到调用对象
        byte[] content = rpcProtocol.getContent();
        String json = new String(content, 0, rpcProtocol.getContentLength());
        RpcInvocation rpcInvocation = JSON.parseObject(json, RpcInvocation.class);
        // RPC 调用判断，返回的结果是否是发过去的请求
        if (!RESP_MAP.containsKey(rpcInvocation.getUuid())) {
            throw new IllegalArgumentException("服务器的响应结果错误");
        }
        // 将 RPC 调用返回的结果保存
        RESP_MAP.put(rpcInvocation.getUuid(), rpcInvocation);
        ReferenceCountUtil.release(msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        Channel channel = ctx.channel();
        if (channel.isActive()) {
            ctx.close();
        }
    }
}
